/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.google.code.p.narcissus.ui.components;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.event.MouseInputAdapter;

import com.google.code.p.narcissus.core.model.ReferenceMetaData;

/**
 *
 * @author jadoj
 */
public class ReferenceImagePanel extends ImagePanel {

	private static final long serialVersionUID = -767986219406298090L;

	private ReferenceMetaData metaData;
    
    private EditionMode currentEditionMode;
    
    private ExclusionZonesCreationListener creationListener;
    
    private ExclusionZonesDeleteListener deletionListener;
    Rectangle currentRect = null;
    Rectangle rectToDraw = null;
    Rectangle previousRectDrawn;
    
    public ReferenceImagePanel() {
    	super(); 
    	setOpaque(true);
        setMinimumSize(new Dimension(10,10));
        creationListener = new ExclusionZonesCreationListener();
        deletionListener = new ExclusionZonesDeleteListener();
        currentEditionMode = EditionMode.ReadOnly;
        metaData = new ReferenceMetaData(new ArrayList<Rectangle>());
	}
    
    

    public void setMetaData(ReferenceMetaData metaData) {
    	if(metaData !=null){
    		this.metaData = metaData;
    	}else{
    		this.metaData = new ReferenceMetaData(new ArrayList<Rectangle>());
    	}
        this.repaint();
    }
    
    public ReferenceMetaData getMetaData(){
    	return this.metaData;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D graph = (Graphics2D) g;
        graph.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
        List<Rectangle> exclusionZones = metaData.getExclusionZones();
        
        if (currentRect != null) {
    		for (int i=0;i< exclusionZones.size()-1 ;i++) {
    			Rectangle rect = exclusionZones.get(i);
    			g.setColor(Color.black);
    			g.drawRect(getScaledValue(rect.x), getScaledValue(rect.y), 
    					getScaledValue(rect.width - 1), getScaledValue(rect.height - 1));
    			g.setColor(new Color(238,233,233,150));
    			g.fillRect(getScaledValue(rect.x), getScaledValue(rect.y), 
    					getScaledValue(rect.width - 1), getScaledValue(rect.height - 1));
			}
    		
    		if(rectToDraw!=null){
    			g.setColor(Color.black);
    			g.drawRect(rectToDraw.x,rectToDraw.y,rectToDraw.width - 1, rectToDraw.height - 1);
    			g.setColor(new Color(238,233,233,150));
    			g.fillRect(rectToDraw.x,rectToDraw.y,rectToDraw.width - 1, rectToDraw.height - 1);
    		}else if(!exclusionZones.isEmpty()){
    			Rectangle rectangle = exclusionZones.get(exclusionZones.size()-1);
    			g.setColor(Color.black);
    			g.drawRect(getScaledValue(rectangle.x), getScaledValue(rectangle.y), 
    					getScaledValue(rectangle.width - 1), getScaledValue(rectangle.height - 1));
    			g.setColor(new Color(238,233,233,150));
    			g.fillRect(getScaledValue(rectangle.x), getScaledValue(rectangle.y), 
    					getScaledValue(rectangle.width - 1), getScaledValue(rectangle.height - 1));
    		}
    	}
    }
    
    
    private class ExclusionZonesDeleteListener extends MouseInputAdapter {
    	 public void mouseClicked(MouseEvent e) {
         	int x = e.getX();
         	int y = e.getY();
         	
         	for (int i=0;i<metaData.getExclusionZones().size(); i++) {
         		Rectangle rect = metaData.getExclusionZones().get(i);
				if(getScaledValue(rect.x) < x && (getScaledValue(rect.x) + getScaledValue(rect.width)) > x &&
						getScaledValue(rect.y) < y && (getScaledValue(rect.y) + getScaledValue(rect.height)) > y){
					metaData.getExclusionZones().remove(rect);
					repaint(getScaledValue(rect.x - 1), getScaledValue(rect.y - 1),getScaledValue(rect.width + 1), getScaledValue(rect.height + 1));
					break;
				}
			}
         }
    }
    
    
    private class ExclusionZonesCreationListener extends MouseInputAdapter {
        public void mousePressed(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            previousRectDrawn = new Rectangle();
            currentRect = new Rectangle(x, y, 0, 0);
            metaData.getExclusionZones().add(currentRect);
            updateDrawableRect(getWidth(), getHeight());
            repaint();
        }

        public void mouseDragged(MouseEvent e) {
            updateSize(e);
        }

        public void mouseReleased(MouseEvent e) {
           updateSize(e);
           metaData.getExclusionZones().get(metaData.getExclusionZones().size()-1).setRect(getNonScaledValue(rectToDraw.x), getNonScaledValue(rectToDraw.y), getNonScaledValue(rectToDraw.width), getNonScaledValue(rectToDraw.height));
           rectToDraw = null;
        }
        
        public void mouseClicked(MouseEvent e) {
        	//setCursor(new Cursor(Cursor.MOVE_CURSOR));
        }

        /* 
         * Update the size of the current rectangle
         * and call repaint.  Because currentRect
         * always has the same origin, translate it
         * if the width or height is negative.
         * 
         * For efficiency (though
         * that isn't an issue for this program),
         * specify the painting region using arguments
         * to the repaint() call.
         * 
         */
        void updateSize(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            currentRect.setSize(x - currentRect.x,
                                y - currentRect.y);
            updateDrawableRect(getWidth(), getHeight());
            Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
            repaint(totalRepaint.x, totalRepaint.y,
                    totalRepaint.width, totalRepaint.height);
        }
    }


    private void updateDrawableRect(int compWidth, int compHeight) {
        int x = currentRect.x;
        int y = currentRect.y;
        int width = currentRect.width;
        int height = currentRect.height;

        //Make the width and height positive, if necessary.
        if (width < 0) {
            width = 0 - width;
            x = x - width + 1; 
            if (x < 0) {
                width += x; 
                x = 0;
            }
        }
        if (height < 0) {
            height = 0 - height;
            y = y - height + 1; 
            if (y < 0) {
                height += y; 
                y = 0;
            }
        }

        //The rectangle shouldn't extend past the drawing area.
        if ((x + width) > compWidth) {
            width = compWidth - x;
        }
        if ((y + height) > compHeight) {
            height = compHeight - y;
        }
      
        //Update rectToDraw after saving old value.
        if (rectToDraw != null) {
            previousRectDrawn.setBounds(
                        rectToDraw.x - 1, rectToDraw.y - 1, 
                        rectToDraw.width + 1, rectToDraw.height + 1);
            
            rectToDraw.setBounds(x, y, width, height);
        } else {
            rectToDraw = new Rectangle(x, y, width, height);
        }
    }



	public EditionMode getCurrentEditionMode() {
		return currentEditionMode;
	}
	
	public int getNonScaledValue(int originalValue) {
        return new Double(((double) originalValue) * 100 / getScalePercentage()).intValue();
    }



	public void setCurrentEditionMode(EditionMode currentEditionMode) {
		if(EditionMode.ReadOnly.equals(currentEditionMode)){
			removeMouseListener(creationListener);
			removeMouseMotionListener(creationListener);
			setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		}else if (EditionMode.inEdtion.equals(currentEditionMode)){
			 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
		     addMouseListener(creationListener);
		     addMouseMotionListener(creationListener);
		}else if (EditionMode.inDeletion.equals(currentEditionMode)){
			//hand cursor until have a good cursor.
			setCursor(new Cursor(Cursor.HAND_CURSOR));
			removeMouseListener(creationListener);
			removeMouseMotionListener(creationListener);
		    addMouseListener(deletionListener);
		    addMouseMotionListener(deletionListener);
		}
		this.currentEditionMode = currentEditionMode;
	}
}
